﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Ioc;
using GalaSoft.MvvmLight.Views;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;


namespace MVVMToolKit.AttachedProperties
{
    public static class WindowHelper
    {
        public static ICommand GetMinCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(MinCommandProperty);
        }

        private static void SetMinCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(MinCommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for MinCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinCommandProperty =
            DependencyProperty.RegisterAttached("MinCommand", typeof(ICommand), typeof(WindowHelper), new PropertyMetadata(null));


        public static ICommand GetCloseCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(CloseCommandProperty);
        }

        private static void SetCloseCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(CloseCommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for CloseCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CloseCommandProperty =
            DependencyProperty.RegisterAttached("CloseCommand", typeof(ICommand), typeof(WindowHelper), new PropertyMetadata(null));



        public static ICommand GetDragMoveCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(DragMoveCommandProperty);
        }

        private static void SetDragMoveCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(DragMoveCommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for DragMoveCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DragMoveCommandProperty =
            DependencyProperty.RegisterAttached("DragMoveCommand", typeof(ICommand), typeof(WindowHelper), new PropertyMetadata(null));




        public static bool GetAttached(DependencyObject obj)
        {
            return (bool)obj.GetValue(AttachedProperty);
        }

        public static void SetAttached(DependencyObject obj, bool value)
        {
            obj.SetValue(AttachedProperty, value);
        }

        // Using a DependencyProperty as the backing store for Attached.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AttachedProperty =
            DependencyProperty.RegisterAttached("Attached", typeof(bool), typeof(WindowHelper), new PropertyMetadata(false,Init));

        private static void Init(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Window window = d as Window;
            if (window == null) return;
           
            if ((bool)e.NewValue)
            {
                SetCloseCommand(d, new RelayCommand(() => window.Close()));
                SetDragMoveCommand(d, new RelayCommand(() => window.DragMove()));
                SetMinCommand(d, new RelayCommand(() => window.WindowState = WindowState.Minimized));
                //设置窗口大小缩放功能
                window.SourceInitialized += (o, e1) =>
                  {
                      HwndSource hwndSource = PresentationSource.FromVisual(window) as HwndSource;
                      if (hwndSource != null)
                      {
                          hwndSource.AddHook(new HwndSourceHook(new WindowResizeHelper(window).WndProc));
                      }
                  };
                //窗口关闭时应该进行清理工作
                window.Closed += (o, e1) =>
                  {
                      ICleanup vm = window.DataContext as ICleanup;
                      if (vm == null) return;
                      vm.Cleanup();
                  };
                window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
        }
        //以下内容用于实现窗口缩放功能
        internal class WindowResizeHelper
        {
            public WindowResizeHelper(Window window)
            {
                AssociatedObject = window;
            }
            private Window AssociatedObject;
            private const int WM_NCHITTEST = 0x0084;
            private readonly int agWidth = 12; //拐角宽度  
            private readonly int bThickness = 4; // 边框宽度  
            private Point mousePoint = new Point(); //鼠标坐标  
            private enum HitTest : int
            {
                HTERROR = -2,
                HTTRANSPARENT = -1,
                HTNOWHERE = 0,
                HTCLIENT = 1,
                HTCAPTION = 2,
                HTSYSMENU = 3,
                HTGROWBOX = 4,
                HTSIZE = HTGROWBOX,
                HTMENU = 5,
                HTHSCROLL = 6,
                HTVSCROLL = 7,
                HTMINBUTTON = 8,
                HTMAXBUTTON = 9,
                HTLEFT = 10,
                HTRIGHT = 11,
                HTTOP = 12,
                HTTOPLEFT = 13,
                HTTOPRIGHT = 14,
                HTBOTTOM = 15,
                HTBOTTOMLEFT = 16,
                HTBOTTOMRIGHT = 17,
                HTBORDER = 18,
                HTREDUCE = HTMINBUTTON,
                HTZOOM = HTMAXBUTTON,
                HTSIZEFIRST = HTLEFT,
                HTSIZELAST = HTBOTTOMRIGHT,
                HTOBJECT = 19,
                HTCLOSE = 20,
                HTHELP = 21,
            }
            public  IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                switch (msg)
                {
                    case WM_NCHITTEST:
                        {
                            this.mousePoint.X = (lParam.ToInt32() & 0xFFFF);
                            this.mousePoint.Y = (lParam.ToInt32() >> 16);
                            #region 测试鼠标位置  
                            // 窗口左上角  
                            if (this.mousePoint.Y - AssociatedObject.Top <= this.agWidth
                                             && this.mousePoint.X - AssociatedObject.Left <= this.agWidth)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTTOPLEFT);
                            }
                            // 窗口左下角　　  
                            else if (AssociatedObject.ActualHeight + AssociatedObject.Top - this.mousePoint.Y <= this.agWidth
                                             && this.mousePoint.X - AssociatedObject.Left <= this.agWidth)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTBOTTOMLEFT);
                            }
                            // 窗口右上角  
                            else if (this.mousePoint.Y - AssociatedObject.Top <= this.agWidth
                             && AssociatedObject.ActualWidth + AssociatedObject.Left - this.mousePoint.X <= this.agWidth)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTTOPRIGHT);
                            }
                            // 窗口右下角  
                            else if (AssociatedObject.ActualWidth + AssociatedObject.Left - this.mousePoint.X <= this.agWidth
                             && AssociatedObject.ActualHeight + AssociatedObject.Top - this.mousePoint.Y <= this.agWidth)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTBOTTOMRIGHT);
                            }
                            // 窗口左侧  
                            else if (this.mousePoint.X - AssociatedObject.Left <= this.bThickness)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTLEFT);
                            }
                            // 窗口右侧  
                            else if (AssociatedObject.ActualWidth + AssociatedObject.Left - this.mousePoint.X <= this.bThickness)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTRIGHT);
                            }
                            // 窗口上方  
                            else if (this.mousePoint.Y - AssociatedObject.Top <= this.bThickness)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTTOP);
                            }
                            // 窗口下方  
                            else if (AssociatedObject.ActualHeight + AssociatedObject.Top - this.mousePoint.Y <= this.bThickness)
                            {
                                handled = true;
                                return new IntPtr((int)HitTest.HTBOTTOM);
                            }
                            else // 窗口移动(也可在窗体MouseLeftButtonDown事件中调用DragMove()方法)，双击最大化，所有剩余鼠标操作映射到标题栏  
                            {
                                //return new IntPtr((int)HitTest.HTCAPTION);
                                return IntPtr.Zero;
                            }
                            #endregion
                        }
                }

                return IntPtr.Zero;
            }
        }
    }
}
